﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace mst_regex
{
    internal class MstParserDse
    {
        private const int GRP_TICKER = 1;
        private const int COL_OPEN = 0;
        private const int COL_HIGH = COL_OPEN + 1;
        private const int COL_LOW = COL_HIGH + 1;
        private const int COL_CLOSE = COL_LOW + 1;
        private const int COL_CHG = COL_CLOSE + 1;
        private const int COL_TRADES = COL_CHG + 1;
        private const int COL_VOLUME = COL_TRADES + 1;
        private const int COL_VALUES = COL_VOLUME + 1;

        private readonly StockPositions _stockPositions;

        public MstParserDse(StockPositions stockPositions)
        {
            _stockPositions = stockPositions;
        }

        public bool ParseDocument(string mstdata, string dsegraph)
        {
            string[] mstLines = mstdata.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
            _stockPositions.EffectiveDate = _mstGetDate(mstLines);
            int spotTrades = _mstGetSpotTrades(mstLines);

            decimal dseHigh, dseLow, dseOpen, dseClose, dseTrades, dseVolume;
            _parseDseCompanyGraph(dsegraph, out dseHigh, out dseLow);
            _mstParseDgen(mstdata, out dseOpen, out dseClose, out dseTrades, out dseVolume);

            if (dseTrades > 0)
            {
                //_stockPositions.AddRecord("00DSEGEN", dseOpen, dseClose, dseHigh, dseLow, dseTrades, dseVolume/*, false*/);
            }

            _mstParseStockRecords(mstLines);
            return true;
        }

        private static DateTime _mstGetDate(IEnumerable<string> mstLines)
        {
            var rex = new Regex(@"(?<year>\d{2,4})-(?<month>\d{1,2})-(?<day>\d{1,2})$",
                                RegexOptions.Multiline | RegexOptions.Compiled);
            foreach (string line in mstLines)
            {
                Match match = rex.Match(line);
                if (match.Success)
                {
                    int Year, Month, Day = 0;
                    if (int.TryParse(match.Groups["year"].Value, out Year) &&
                        int.TryParse(match.Groups["month"].Value, out Month) &&
                        int.TryParse(match.Groups["day"].Value, out Day))
                    {
                        return new DateTime(Year, Month, Day);
                    }
                }
            }
            return DateTime.Today;
        }

        private static int _mstGetSpotTrades(IEnumerable<string> mstLines)
        {
            int Trades = 0;
            var rex = new Regex(@"scrips\s+traded\s+in\s+Spot\s+Market\s+=\s+(?<trades>\d)+$",
                                RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.Compiled);
            foreach (string line in mstLines)
            {
                Match match = rex.Match(line);
                if (match.Success && int.TryParse(match.Groups["trades"].Value, out Trades))
                {
                    return Trades;
                }
            }
            return Trades;
        }

        private static void _parseDseCompanyGraph(string dsegraph, out decimal high, out decimal low)
        {
            high = 0;
            low = 0;

            var rex = new Regex(@"value:.*?([\d\.]+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            MatchCollection matches = rex.Matches(dsegraph);
            if (matches.Count == 2)
            {
                decimal.TryParse(matches[0].Groups[1].Value, out high);
                decimal.TryParse(matches[1].Groups[1].Value, out low);
            }
        }

        private static void _mstParseDgen(string mstdata,
                                          out decimal open, out decimal close,
                                          out decimal trades, out decimal volume)
        {
            open = close = trades = volume = 0;

            //A. NO. OF TRADES                :                 210841
            var rxTrades = new Regex(@"TRADES\s+:\s+(\d+)", RegexOptions.IgnoreCase);

            //C. VALUE(Tk)                    :         18873757475.85
            var rxValue = new Regex(@"VALUE\(Tk\)\s+:\s+([\d\.]+)", RegexOptions.IgnoreCase);

            // DGEN          6172.54289    6153.67737
            var rxDgen = new Regex(@"DGEN\s+(?<open>[\d\.]+)\s+(?<close>[\d\.]+)", RegexOptions.IgnoreCase);

            Match match = rxTrades.Match(mstdata);
            if (match.Success)
            {
                decimal.TryParse(match.Groups[1].Value, out trades);
            }

            match = rxValue.Match(mstdata);
            if (match.Success)
            {
                decimal vol = 0;
                if (decimal.TryParse(match.Groups[1].Value, out vol))
                {
                    volume = vol/10000000;
                }
            }

            match = rxDgen.Match(mstdata);
            if (match.Success)
            {
                decimal.TryParse(match.Groups["open"].Value, out open);
                decimal.TryParse(match.Groups["close"].Value, out close);
            }
        }

        private static void _mstParseStockRecords(IEnumerable<string> mstLines)
        {
            //ABBANK      1360.00  1399.00  1352.25  1393.50    2.84   8826   628635   868.870
            //ACI          396.50   405.00   394.10   396.00    -.27    425    54650    21.655
            var rx = new Regex(@"^(\S+)\s+(\s+[\d\.\-]+){8}$",
                               RegexOptions.Multiline | RegexOptions.Compiled);
            foreach (string line in mstLines)
            {
                Match match = rx.Match(line);
                if (match.Success)
                {
                    decimal high = 0, low = 0, open = 0, close = 0, trades = 0, volume = 0;
                    string ticker = null;

                    for (int grpNum = 1; grpNum < match.Groups.Count; grpNum++)
                    {
                        if (grpNum == GRP_TICKER)
                        {
                            ticker = match.Groups[grpNum].Captures[0].Value.Trim();
                        }
                        else
                        {
                            int captureCtr = 0;
                            foreach (Capture capture in match.Groups[grpNum].Captures)
                            {
                                switch (captureCtr)
                                {
                                    case COL_OPEN:
                                        decimal.TryParse(capture.Value.Trim(), out open);
                                        break;
                                    case COL_HIGH:
                                        decimal.TryParse(capture.Value.Trim(), out high);
                                        break;
                                    case COL_LOW:
                                        decimal.TryParse(capture.Value.Trim(), out low);
                                        break;
                                    case COL_CLOSE:
                                        decimal.TryParse(capture.Value.Trim(), out close);
                                        break;
                                    case COL_CHG:
                                        //decimal.TryParse(capture.Value.Trim(), out change);
                                        break;
                                    case COL_TRADES:
                                        decimal.TryParse(capture.Value.Trim(), out trades);
                                        break;
                                    case COL_VOLUME:
                                        decimal.TryParse(capture.Value.Trim(), out volume);
                                        break;
                                    case COL_VALUES:
                                        //decimal.TryParse(capture.Value.Trim(), out value);
                                        break;
                                }
                                captureCtr++;
                            }
                        }
                    }

                    //if (trades > 0) _stockPositions.AddRecord(ticker, open, close, high, low, trades, volume, true);
                }
            }
        }
    }
}